﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GeneralServices.PatternCommand
{
    /// <summary>
    /// 
    /// </summary>
    public abstract class AbstractInvoker
    {
        #region Attributs
        /// <summary>
        /// 
        /// </summary>
        private int _placement = 0;

        /// <summary>
        /// 
        /// </summary>
        public static int sizeHisto = 20;
        #endregion

        #region Properties
        /// <summary>
        /// 
        /// </summary>
        private List<AbstractCommand> Commands
        {
            get;
            set;
        }

        /// <summary>
        /// 
        /// </summary>
        public IReceiver Receiver
        {
            get;
            private set;
        }

        #endregion

        #region Constructeur
        /// <summary>
        /// 
        /// </summary>
        /// <param name="receiver"></param>
        public AbstractInvoker(IReceiver receiver)
        {
            Receiver = receiver;
            Commands = new List<AbstractCommand>();
        }
        #endregion

        #region Méthodes
        /// <summary>
        /// 
        /// </summary>
        /// <param name="_args"></param>
        public abstract void Action(AbstractCommandArgs _args);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="levels"></param>
        public void Redo(int levels)
        {
            // Perform redo operations
            for (int i = 0; i < levels; i++)
            {
                //if (_placement < Commands.Count - 1)
                if (_placement < Commands.Count )
                {
                    AbstractCommand command = Commands[_placement++];
                    command.Execute();
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="levels"></param>
        public void Undo(int levels)
        {
            // Perform undo operations
            for (int i = 0; i < levels; i++)
            {
                if (_placement > 0)
                {
                    AbstractCommand command = Commands[--_placement] as AbstractCommand;
                    command.UnExecute();
                }
            }
        }
 
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        protected void AddCommand(AbstractCommand command)
        {
            Commands.Add(command);
            _placement++;

            // Archivage
            if (_placement > sizeHisto)
            {
                Commands.RemoveRange(0, _placement - sizeHisto);
                _placement = sizeHisto;
            }
        }
        #endregion
    }
}
